package com.java.util;

import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
/**
 * 
 * @author zhongbh
 *
 */
public class DigitalToChinese {
	private static final String[][] CHINESE_NUMS = {{"零"},{"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"},{"仟","佰","拾",""},{"","萬","億","兆","京"}};
	private static final String ZERO = CHINESE_NUMS[0][0];
	private static final String[] ZERO_TO_NINE = CHINESE_NUMS[1];
	private static final String[] SMALL_UNIT = CHINESE_NUMS[2];
	private static final String[] BIG_UNIT = CHINESE_NUMS[3];
	@Test
	public void MyTest(){ 
		System.out.println(toChineseNum("12004000000000540"));
		System.out.println(toChineseNum("12004100000000540"));
		System.out.println(toChineseNum("12004000001000545"));
	}
	/**
	 * 数字字符串转成中文大写形式,无小数部分,单位上限为‘京’
	 * @param str
	 * @return String
	 */
	public static String toChineseNum(String str){
		Long longNum = null;
		int size = 0;
		String number = null;
		try{
			/**
			 * 字符串检查顺便去除前面的“0”,若数字超过‘京’的范围,抛出一个异常,返回错误信息
			 */
			longNum = Long.parseLong(str);
			if(longNum==0L)
				return ZERO;
			if(longNum.toString().length()>17)
				throw new NumberFormatException();
			number = longNum.toString();
			size = number.length();
		}catch(NumberFormatException e){
			return "ERROR NUMBER!";
		}
		String chineseNum = "";
		/**
		 * 定义2个数组：一个存数字字符串,另一个存对每段数字字符串转换后的中文大写值
		 * [1, 2004, 0000, 1000, 0540] 对应[壹,贰仟零肆,零,壹仟,零伍佰肆拾]
		 */
		int forNum = size%4==0?size/4:(size/4+1);
		String[] temps = new String[forNum];
		String[] tempChinese = new String[forNum];
		/**
		 * 将字符串从低位往高位(从右往左)截取,初始化数组temps(按下标从大到小赋值)
		 */
		for(int i=0;i<forNum;i++){
			temps[(forNum-1)-i] = number.substring((number.length()-4-4*i)<0?0:(number.length()-4-4*i), number.length()-4*i);
		}
		for(int j=0;j<temps.length;j++){
			/**
			 * 遍历temps数组,去除前导’0‘:0540变为540
			 */
			String temp = String.valueOf(Integer.valueOf(temps[j]));
			String tempResult = "";
			List<String> list = new ArrayList<String>();
			for(int t = 0;t<temp.length();t++){
				/**
				 * 取得每位数字(从左到右,高位到低位),对应的大写数字t1: 0,零 2,贰
				 */
				String t1 = ZERO_TO_NINE[Integer.valueOf(String.valueOf(temp.charAt(t)))];
				/**
				 * ’零‘不加单位,非零补上单位{"仟","佰","拾",""}
				 */
				String t2 = t1.equals(ZERO)?ZERO:(t1+SMALL_UNIT[(4-temp.length())+t]);
				/**
				 * 每位数字转换完后,存入一个列表（之前先判断列表中有无该元素：4位数最多出现一个’零‘,出现第二个’零‘,可直接丢弃）
				 */
				if(!list.contains(t2)){
					list.add(t2);
					/**
					 * 除去多余的’零‘后,组装成字符串,（2004:贰仟零肆,0540:伍佰肆拾零 1000:壹仟零）
					 * 该字符串,左面与中间不会有多余的’零‘,右边可能有’零‘
					 */
					tempResult += t2;
				}
			}
			/**
			 * 若转换后字符串以“零”结尾,则截除,原来为字符串就为“零”,则截完变“”空字符串；
			 */
			tempResult = tempResult.endsWith(ZERO)?tempResult.substring(0, tempResult.length()-1):tempResult;
			/**
			 * 第二次循环开始(j>0),如原字符串（0233）小于4位,则在前面补“零”：得结果如【壹,贰仟零肆,零,零,零伍佰肆拾】,放入数组tempChinese
			 */
			tempResult = (j>0&&temp.length()<4)?(ZERO+tempResult):tempResult; 
			tempChinese[j] = tempResult;
		}
		for(int k=0;k<tempChinese.length;k++){
			/**
			 * 遍历数组,第二次循环开始(k>0),若当前字符串对应数字为4位（不包括前面的0）且前一个字符串为“零”,则在当前字符串前补零
			 */
			tempChinese[k] = (k>0&&String.valueOf(Integer.valueOf(temps[k])).length()==4&&tempChinese[k-1].equals(ZERO))?(ZERO+tempChinese[k]):tempChinese[k];
			/**
			 * 组装数组,若字符串为“零”,直接丢弃,取字符串,添加相应的单位{"","萬","億","兆","京"}
			 */
			chineseNum += !ZERO.equals(tempChinese[k])?(tempChinese[k]+BIG_UNIT[(tempChinese.length-1)-k]):"";
		}
		return chineseNum;
	}
}
